Release 1.3.20 — domains CLI, Remotion fix, new commands - #11
Merged
Conversation
render and still commands didn't pass an output path, so Remotion defaulted to its project dir (~/.iris/remotion/out/). Now defaults to $PWD/out/<composition>.<ext> and prints the path. Fixes #77344, #77345 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…stry) Atlas Datasets CLI (iris atlas:datasets): - schemas list/show/create — manage dataset blueprints - records list/show/summary/add/update/delete/upsert — full CRUD - export — CSV/JSON export for QuickBooks Desktop - audit — data quality scan (flags $0 billing, missing fields) Genesis Validation: - validateComponents() now async — fetches valid types from API - Fallback to 152-type hardcoded set when API unreachable - pages set now validates before API call - VALID_COMPONENT_TYPES expanded from 30 → 152 (all Vue components) - COMPONENT_REGISTRY expanded with categories + required props - component-registry command fetches from API with category grouping How-To Recipes (3 new): - atlas-datasets.md — general dataset CLI usage - pathways-cfo-workflow.md — Servis AI → Atlas → QuickBooks pipeline - expose-dataset-api.md — REST API + pages + agent access Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ands - Fix deals create: billing_interval → interval (wrong payload key) - Fix deals create: choices one_time/monthly → one-time/month (API mismatch) - Add deals delete: cancel existing payment gate via CLI - Add deals update: modify amount/scope/interval/fees on existing gate - Add --pass-fees/--absorb-fees/--fee-percent/--fee-flat to create & update - Update command preserves interval from existing deal billing_type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds `iris hive domains proxy <subdomain> <target>` which: 1. Creates Cloudflare DNS record (via wrangler) 2. Creates Cloudflare Worker route (via wrangler) 3. Creates domain mapping in fl-api Also adds `iris hive domains list` and `iris hive domains remove`. Example: iris hive domains proxy comic https://comic-book-factory.vercel.app → comic.heyiris.io proxied to the Vercel app Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This release expands the IRIS CLI with new Atlas dataset write capabilities, Hive domain mapping/proxy management, and improved Pages component validation/registry handling, alongside documentation scaffolds for Atlas datasets and a Remotion output-path adjustment.
Changes:
- Add new “how-to” scaffold docs for Atlas datasets usage, exposing dataset APIs, and the Pathways CFO workflow.
- Update CLI behavior for Remotion default output paths and Pages component validation/registry fetching.
- Add/extend CLI commands for Atlas datasets (schema create + record CRUD/upsert), Hive domains proxy/list/remove, and Deals payment-gate update/delete.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| scaffold/how-to/pathways-cfo-workflow.md | New end-to-end workflow recipe for Pathways CFO pipeline. |
| scaffold/how-to/expose-dataset-api.md | New recipe describing REST access patterns for Atlas datasets. |
| scaffold/how-to/atlas-datasets.md | New general recipe for Atlas datasets CLI usage. |
| scaffold/how-to/README.md | Adds recipe index entries for new how-to docs. |
| packages/opencode/src/cli/cmd/platform-remotion.ts | Changes default render/still outputs to ./out/... and prints output path. |
| packages/opencode/src/cli/cmd/platform-pages.ts | Switches public URL base, makes component validation async with API-backed registry, and expands component registry output. |
| packages/opencode/src/cli/cmd/platform-leads.ts | Adjusts deals payment-gate interval + adds update/delete commands + processing fee flags. |
| packages/opencode/src/cli/cmd/platform-hive.ts | Adds iris hive domains proxy/list/remove with Cloudflare + fl-api domain mapping integration. |
| packages/opencode/src/cli/cmd/platform-atlas-datasets.ts | Adds schema create and record write commands (add/update/delete/upsert). |
| packages/opencode/src/cli/cmd/command-groups.ts | Categorizes atlas:datasets under the atlas command group. |
Comments suppressed due to low confidence (1)
packages/opencode/src/cli/cmd/platform-hive.ts:11
- This file redefines
IRIS_APIlocally instead of using the exportedIRIS_API/PLATFORM_URLSfromcli/cmd/iris-api.ts, which is the repo’s single source of truth for platform base URLs. Using the shared constant avoids drift (e.g., different defaults/fallbacks) and respects the ~/.iris/sdk/.env preload logic iniris-api.ts.
// Use iris-api base for Hive endpoints
const IRIS_API = process.env.IRIS_API_URL ?? "https://freelabel.net"
async function hiveFetch(path: string, options: RequestInit = {}) {
return irisFetch(path, options, IRIS_API)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2787
to
+2791
| await flApiFetch(`/api/v1/domain-mappings/${existing.id}`, { | ||
| method: "PUT", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ proxy_target: target, mapping_mode: "proxy", mapping_type: "proxy" }), | ||
| }) |
Comment on lines
+2721
to
+2726
| // Create DNS A record (proxied, dummy IP — Worker intercepts) | ||
| try { | ||
| execSync( | ||
| `npx wrangler dns create ${baseDomain} --type A --name ${sub} --content 192.0.2.1 --proxied`, | ||
| { stdio: "pipe", timeout: 30000 } | ||
| ) |
Comment on lines
+3323
to
+3324
| if (!args.amount && !args.scope && !args.interval && !args["pass-fees"] && !args["absorb-fees"]) { | ||
| prompts.log.error("Provide at least one field to update: --amount, --scope, --interval, or --pass-fees") |
Comment on lines
+3340
to
+3342
| // Delete existing and recreate with updated values | ||
| const delRes = await irisFetch(`/api/v1/leads/${args.id}/payment-gate`, { method: "DELETE" }) | ||
| if (!(await handleApiError(delRes, "Remove existing payment gate"))) return |
Comment on lines
+83
to
+90
| ## Data flow diagram | ||
| ``` | ||
| Service AI ──→ IRIS Agent ──→ Atlas Dataset (cases) ──→ CSV Export | ||
| ↓ ↓ ↓ ↓ | ||
| Case details Aggregates Audit flags QuickBooks | ||
| + Services from Drive $0 billing Desktop | ||
| + Billing + Email Missing docs import | ||
| ``` |
Comment on lines
+247
to
+259
| // Validate components if the update touches json_content.components | ||
| if (args.path.startsWith("json_content.components") || args.path === "json_content") { | ||
| const target = args.path === "json_content" ? parsed : json | ||
| const validation = await validateComponents(target) | ||
| if (!validation.valid) { | ||
| sp.stop("Validation failed", 1) | ||
| for (const err of validation.errors) { | ||
| if (err) prompts.log.error(err) | ||
| } | ||
| prompts.outro("Done") | ||
| return | ||
| } | ||
| } |
Comment on lines
+740
to
+760
| async function getValidComponentTypes(): Promise<Set<string>> { | ||
| if (_cachedValidTypes) return _cachedValidTypes | ||
|
|
||
| try { | ||
| const { IRIS_API } = await import("./iris-api") | ||
| const res = await irisFetch("/api/v1/pages/schema-registry", {}, IRIS_API) | ||
| if (res.ok) { | ||
| const body = (await res.json()) as any | ||
| const types: string[] = body?.data?.types ?? [] | ||
| if (types.length > 0) { | ||
| _cachedValidTypes = new Set(types) | ||
| return _cachedValidTypes | ||
| } | ||
| } | ||
| } catch { | ||
| // API unreachable — use fallback | ||
| } | ||
|
|
||
| _cachedValidTypes = FALLBACK_COMPONENT_TYPES | ||
| return _cachedValidTypes | ||
| } |
Comment on lines
21
to
25
| const env = process.env.IRIS_ENV ?? "production" | ||
| return env === "local" | ||
| ? `http://local.iris.freelabel.net:9300/p/${slug}` | ||
| : `https://heyiris.io/p/${slug}` | ||
| : `https://freelabel.net/p/${slug}` | ||
| } |
Comment on lines
+54
to
+56
| const comp = args.composition as string | ||
| const output = (args.output as string) || join(process.cwd(), "out", `${comp}.mp4`) | ||
| const cmdArgs = ["render", comp, output] |
Comment on lines
+2685
to
+2689
| const FL_API = process.env.FL_API_URL ?? "https://raichu.heyiris.io" | ||
|
|
||
| async function flApiFetch(path: string, options: RequestInit = {}) { | ||
| return irisFetch(path, options, FL_API) | ||
| } |
mayoalexander
added a commit
that referenced
this pull request
Aug 6, 2026
…ing's dead route TWO THINGS, ONE WORKFLOW. 1. FIX — leads:meeting POSTed /api/chat/start, which is DEAD. It 404s on every call. platform-eval.ts already hit and fixed this exact failure (#146509: "the old harness POSTed to the dead raichu.heyiris.io/api/chat/start route → 404 on every test → false 0/7") by switching to streamAgentChat. leads:meeting never got the same fix, so a command whose entire purpose is turning a transcript into lead intel has been failing at the last step — AFTER reading the file and printing "Analyzing transcript with AI…", which makes it look supported right up until it produces nothing. Its default agent was also hardcoded to #11, which returns "Resource not found". 2. NEW — `iris meetings`. Wispr Flow keeps one directory per meeting under ~/Library/Application Support/Wispr Flow/meetings/<uuid>/refined.ndjson. Nothing surfaced it, so using a call meant finding the UUID by hand, converting NDJSON, and passing a path. Now: iris meetings list recent sessions iris meetings 8ba439fd --bloq 570 summarise + file it iris meetings 8ba439fd --export out.txt just the transcript iris meetings 8ba439fd --bloq 570 --raw verbatim, no AI Sessions resolve by id prefix. --bloq finds or CREATES a "Meetings" list, so every client project accumulates its calls in the same place without anyone deciding where they go — a standard workflow rather than a convention people have to remember. DELIBERATE CHOICES: - Speakers are surfaced as diarised ids, not guessed names. Diarisation splits one person across ids routinely; a wrong name silently mis-attributes a commitment, which is worse than no name. --speaker 2=Arthur labels them when you know. - Every export carries a header saying Wispr records SYSTEM audio, so your own mic may be absent and one side of the conversation can be missing. Verified on a real 56-minute client call where the local speaker was entirely uncaptured — reading that transcript without the warning would give a confidently one-sided account. - Extraction failure is NOT fatal. It falls back to filing the raw transcript, because a filed transcript beats a lost meeting. - The extraction prompt forbids inventing names, numbers, dates or commitments, and asks it to flag one-sidedness rather than infer the missing half. Verified end to end on a real 222-segment, 56:47 client call: listed, extracted, created the Meetings list on bloq 570 and filed item #179213 with accurate decisions and owners. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017HeisVSNVkwQPv3zvoJJUA
mayoalexander
added a commit
that referenced
this pull request
Aug 19, 2026
…ed on a 404 `iris integrations list` collapsed every probe failure into "unverified — could not probe", which tells the reader nothing and cost real debugging hours. Two worse bugs surfaced while fixing that: 1. The gmail and google-drive probes returned "verified" for ANY response that was not 401/403 — including 404 and 500. Both probe endpoints currently 404 (/api/v1/leads/0/gmail-threads, /api/v1/integrations/exec), so Gmail has been rendering a green [verified] while its probe does not resolve at all. The health signal on those rows was meaningless. 2. Probe results were keyed by integration TYPE, not id, and the drive probe never passed integration_id. All three google-drive accounts (#4, #11, #12) therefore shared one result taken from whichever connection the API picks by default — two accounts could be dead and every row would show the third's status. The comment directly above that code says multi-account visibility is the point of the command. Changes: - Probes return { state, reason, fix } instead of a bare string, so every row states its cause and, where one exists, the command that fixes it. - New "unknown" state, distinct from failure. A 404 on the PROBE path means we cannot determine the integration's health; claiming either verified or unverified would be unsupported. Rendered neutral rather than red, because the fix belongs to us, not the user. - Network failures are classified — connection refused / timeout / DNS — rather than collapsing into one string. - Results keyed by integration id; the drive probe passes integration_id so each account is genuinely probed. - The calendar probe distinguishes bridge-not-running, no-bridge-key, key-rejected and HTTP-n, each with `iris hive doctor` as the fix. before gmail #3 [verified] after gmail #3 [unknown] — probe endpoint returned 404; status not determined before google-calendar #2 [unverified] — could not probe after google-calendar #2 [unverified] — no bridge key configured → iris hive doctor Verified by running the command from source, not by reading the diff. Typecheck clean; the remaining tsc error (session/llm.ts:88 TS2589) is pre-existing and reproduces with this change stashed. Refs #180929, #181016 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mayoalexander
added a commit
that referenced
this pull request
Sep 5, 2026
`iris eval run` reported "Tests passed 7/7". It counted every non-empty reply as
a pass:
const passed = results.filter((r) => r.status === "completed").length
// "completed" = summary.trim().length > 0
Four of the seven scenarios asserted NOTHING — introduction, creative,
tool-awareness, summary — so they passed by existing. The two that did have
keyword checks had their results printed and then excluded from the count. The
number could not go down, which made it a liveness probe wearing a score's
clothes.
Two changes.
1. A test with no assertion cannot pass; it can only run. Verdicts are now
pass | fail | unscored, and the summary reads "3 / 3 scored · 4 unscored
(ran, asserted nothing)" instead of 7/7. Same agent, same run, honest number.
2. A second suite that tests THIS agent rather than the model underneath it.
`core` (Eiffel Tower, 17*24, a haiku) passes identically whether the agent's
tools, YAML registry and integrations work or are entirely broken, because
none of it is exercised. `agent` asserts:
tool-use the agent CALLED a tool — toolsUsed non-empty. The old
"what tools do you have?" is a self-report the agent will
happily give from its prompt header while every one of them
is unreachable.
grounding it reached the workspace at all
no-fabrication it declines to invent when asked about something that does
not exist
Verified against PATTY (anomalyco#420), not asserted: tool-use called
Pathways_get_firm_directory, grounding called SearchKnowledgeBaseTool. And it
fails honestly — agent #11 returned "Resource not found" and scored 0/3 rather
than passing vacuously.
no-fabrication is documented in-code as flaky BY CONSTRUCTION, because it is a
lexical proxy for a semantic property: the same agent on the same prompt hedged
in wording my list matched once and missed twice. The caveat says to read the
reply on a failure rather than conclude fabrication, and not to put it in a
threshold. Better to ship the limitation written down than a check that looks
deterministic and is not.
No MCP change. `iris_run` already executes any CLI command, so the MCP server
stays at seven tools and picks this up for free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQ9915AheUUs2qL2D2u62K
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
iris hive domains proxy/list/remove— manage domain mappings + Cloudflare from CLITest plan
iris hive domains listshows existing mappingsiris hive domains proxy comic https://comic-book-factory.vercel.app --base-domain freelabel.netcreates mappingiris remotion render SocialPostoutputs to./out/SocialPost.mp4🤖 Generated with Claude Code